package com.literature.search.file.task.thread;

import com.literature.search.core.entity.FileDocument;
import com.literature.search.core.entity.PageContent;
import com.literature.search.core.entity.PictureParse;
import com.literature.search.core.enums.FileEsStateEnum;
import com.literature.search.core.utils.SpringApplicationContext;
import com.literature.search.file.service.IElasticService;
import com.literature.search.file.service.IFileService;
import com.literature.search.file.task.data.TaskData;
import com.literature.search.file.task.exception.TaskRunException;
import com.literature.search.file.task.executor.TaskExecutor;
import com.literature.search.file.task.executor.TaskExecutorFactory;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: DangKong
 * @Date: 2023/3/2 22:44
 * @Description:
 */
@Slf4j
public class MainTask implements RunnableTask {

    private final TaskExecutor taskExecutor;

    private final TaskData taskData = new TaskData();

    /**
     * @Description // 初始化任务，指定一个
     * @Param [fileDocument]
     **/
    public MainTask(FileDocument fileDocument) {
        taskData.setFileDocument(fileDocument);
        taskData.setThumbFilePath(""); // 缩略图路径
        taskData.setThumbPageFilePathList(null); // 页面缩略图路径
        taskData.setTxtFilePathList(null); // 每个页面的文本路径
        taskData.setPngFilePathList(null); // 提取的图片路径
        this.taskExecutor = TaskExecutorFactory.getTaskExecutor();
    }


    @Override
    public void success() {

        taskData.getFileDocument().setFileEsState(FileEsStateEnum.SUCCESS);  // 设置文档的索引状态为成功
        updateTaskStatus(); // 更新文档的状态
        // 更新文档的数据
        IFileService fileService = SpringApplicationContext.getBean(IFileService.class);

        fileService.updateFile(taskData.getFileDocument());
    }

    @Override
    public void failed(Throwable throwable) {
        log.error("解析文件报错啦", throwable);
        String errorMsg = throwable.getMessage();
        taskData.getFileDocument().setFileEsState(FileEsStateEnum.FAIL);
        taskData.getFileDocument().setErrorMsg(errorMsg +" " + throwable.getCause());
        updateTaskStatus();
    }

    @Override
    public void fallback() {
        // 删除es中的数据，删除thumb数据，删除存储的txt文本文件
        try {
            List<String> thumbPageFilePathList = taskData.getThumbPageFilePathList();
            List<String> txtFilePathList = taskData.getTxtFilePathList();
            List<String> pngPathList = taskData.getPngFilePathList();

            // 清除过程中失败的过程文件
            removeFileIfExist(thumbPageFilePathList);
            removeFileIfExist(txtFilePathList);
            removeFileIfExist(pngPathList);

        } catch (IOException e) {
            log.error("删除文件路径 ==> 失败信息{}", e);
        }
        // 删除相关的文件
        removeExistGridFsAndEs();

    }

    private void removeFileIfExist(List<String> FilePathList) throws IOException {
        for(String filePath : FilePathList) {
            if (StringUtils.hasText(filePath) && new File(filePath).exists()) {
                Files.delete(Paths.get(filePath));
            }
        }

    }

    @Override
    public void run() {
        FileDocument fileDocument = taskData.getFileDocument();
        if (null == taskExecutor || fileDocument == null) {
            log.error("执行文件{}报错",fileDocument);
            throw new TaskRunException("当前执行器初始化失败！");
        }
        if (StringUtils.hasText(fileDocument.getThumbId()) || fileDocument.getPageContentList()!=null) { // 如果文档已经存在
            removeExistGridFsAndEs(); // 删除已经存在的文本文件和缩略图文件
        }
        // 更新子任务数据,开始更新状态，开始进行解析等等
        taskData.getFileDocument().setFileEsState(FileEsStateEnum.ON_PROCESS);
        updateTaskStatus();
        // 调用执行器执行任务
        try {
            this.taskExecutor.execute(taskData);
        } catch (TesseractException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void updateTaskStatus() {
        IFileService fileService = SpringApplicationContext.getBean(IFileService.class); // 获取文件服务
        FileDocument fileDocument = taskData.getFileDocument();
        try {
            fileService.updateEsState(fileDocument, fileDocument.getFileEsState(), fileDocument.getErrorMsg());
        } catch (TaskRunException e) {
            throw new TaskRunException("更新文档状态失败", e);
        }
    }


    /**
     * @Description 删除已经存在的文本文件和缩略图文件以及提取出的图片
     * @Param []
     **/
    private void removeExistGridFsAndEs() {
        FileDocument fileDocument = taskData.getFileDocument(); // 获取文档

        List<PageContent> pageContentList = fileDocument.getPageContentList();
        ArrayList<String> fileIdList = new ArrayList<>();
        for (PageContent pageContent : pageContentList) {
            fileIdList.add(pageContent.getThumbId());
        }
        List<PictureParse> pictureParseList = fileDocument.getPictureParseList();
        for (PictureParse pictureParse : pictureParseList) {
            fileIdList.add(pictureParse.getGridfsId());
        }
        IFileService fileService = SpringApplicationContext.getBean(IFileService.class);
        fileService.deleteGridFs(String.valueOf(fileIdList));

        //删除es中的数据
        IElasticService elasticService = SpringApplicationContext.getBean(IElasticService.class);
        elasticService.deleteById(fileDocument.getId());


    }
}
